﻿Imports <xmlns:eopr="http://schemas.microsoft.com/xps/2005/06">
Imports GoogleDesktopAPILib
Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.IO.Packaging
Imports System.Windows.Xps.Packaging
Imports System.Windows.Xps
Imports System.Text
Imports System.IO
Imports System.Xml.Linq




<ComClass(Indexer.ClassId, Indexer.InterfaceId, Indexer.EventsId)> _
Public Class Indexer

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "5857c73e-9f70-4ab0-bad0-cee4c8df4a7e"
    Public Const InterfaceId As String = "9519145a-8e35-401e-b7f5-0e498e17ebc1"
    Public Const EventsId As String = "e3d73536-9fd6-4fa5-8d12-e045f9f78a62"
#End Region


#Region "Const"
    ''' <summary>
    ''' returned when a crawler component tries to register for an already handled extension
    ''' </summary>
    ''' <remarks></remarks>
    Private Const E_EXTENSION_REGISTERED As Integer = &H80040001

    ''' <summary>
    ''' specifies that the component must register before performing any operations
    ''' </summary>
    ''' <remarks></remarks>
    Private Const E_COMPONENT_NOT_REGISTERED As Integer = &H80040002
    '''<summary>
    ''' returned when a component tries to use an inexistent schema
    '''</summary>
    Private Const E_NO_SUCH_SCHEMA As Integer = &H80040003
    '''<summary>
    ''' returned when a component tries to use an inexistent property
    ''' </summary>
    Private Const E_NO_SUCH_PROPERTY As Integer = &H80040004

    '''<summary>
    ''' specifies that the component has been disabled by the user
    ''' </summary>
    Private Const E_COMPONENT_DISABLED As Integer = &H80040005


    '''<summary> 
    ''' specifies that the component is already registered
    ''' </summary> 
    Private Const E_COMPONENT_ALREADY_REGISTERED As Integer = &H80040006

    '''<summary>
    ''' specifies that indexing is paused and any sent events will be ignored
    ''' </summary>
    Private Const S_INDEXING_PAUSED As Integer = &H80040007

    '''<summary>specifies that the event was rejected because of data size limits</summary>
    Private Const E_EVENT_TOO_LARGE As Integer = &H80040008

    ''' <summary>
    ''' specifies that Google Desktop is not running
    ''' </summary>
    ''' <remarks></remarks>
    Private Const E_SERVICE_NOT_RUNNING As Integer = &H80040009

    '''<summary>specifies that Google Desktop is not running</summary>
    Private Const E_INVALID_EVENT_FLAGS As Integer = &H8004000A

    '''<summary>specifies that the component is prohibited by the user's group policy</summary>
    Private Const E_COMPONENT_PROHIBITED As Integer = &H8004000B

    '''<summary>specifies that the historical event sent could not be delivered immediately and a delay is recommended before sending again</summary>
    Private Const E_SEND_DELAYED As Integer = &H8004000C


    '''<summary>specifies that the provided property has been truncated due to size limits</summary>
    Private Const S_PROPERTY_TRUNCATED As Integer = &H8004000D

    '''<summary>specifies that the provided property is too large and cannot be accepted</summary>
    Private Const E_PROPERTY_TOO_LARGE As Integer = &H8004000E


    '''<summary>returned when a property is not set</summary>
    Private Const E_PROPERTY_NOT_SET As Integer = &H8004000F

    '''<summary>returned when the Google Destop system is exiting.</summary>
    Private Const E_SERVICE_IS_EXITING As Integer = &H80040010

    '''<summary> returned when the application that made the call is exiting</summary>
    Private Const E_APPLICATION_IS_EXITING As Integer = &H80040011

    '''<summary> specifies that the event could not be delivered and a re-send is required</summary>
    Private Const E_RETRY_SEND As Integer = &H80040012

    '''<summary>
    ''' specifies that the event could not be delivered because required
    ''' resources were not available and the send operation timed out
    ''' </summary> 
    Private Const E_SEND_TIMEOUT As Integer = &H80040013

    '''<summary> specifies that the gadget registration was cancelled by the user</summary>
    Private Const E_REGISTRATION_CANCELLED_BY_USER As Integer = &H80040014

    '''<summary>specifies that the search has been locked by the user</summary>
    Private Const E_SEARCH_LOCKED As Integer = &H80040015

#End Region



    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()


        SettingLog()


    End Sub

    Private Shared Sub SettingLog()
        Dim t As Type = GetType(Indexer)

        Dim LogLocation = My.Computer.FileSystem.CombinePath(My.Computer.FileSystem.GetParentPath(t.Assembly.Location), "log")

        With My.Application.Log.DefaultFileLogWriter

            .CustomLocation = LogLocation
            .Location = Logging.LogFileLocation.Custom
            .BaseFileName = "log"
            .LogFileCreationSchedule = Logging.LogFileCreationScheduleOption.Daily
            .AutoFlush = True

        End With

        'My.Application.Log.TraceSource.Switch.Level = SourceLevels.Error Or SourceLevels.Information Or SourceLevels.Warning

        My.Application.Log.WriteEntry("Assembly.Location :" & t.Assembly.Location, TraceEventType.Information)
    End Sub

    Private Shared MyGuid As String = "{" & ClassId & "}"


    Public Sub RegisterIndexer()

        Try

            Dim gdsReg As New GoogleDesktopIndexingComponentRegister

            Dim asminfo As New ApplicationServices.AssemblyInfo(Assembly.GetAssembly(GetType(Indexer)))


            Dim componentdesc = New Object(5) {"Title", asminfo.Title, "Description", asminfo.Description, "Icon", "no icon"}

            gdsReg.RegisterIndexingComponent(MyGuid, componentdesc)



            My.Application.Log.WriteEntry("Registration Component Successfully!", TraceEventType.Information)

            My.Application.Log.WriteEntry("Registration Completed successfully!", TraceEventType.Information)

            'MessageBox.Show("Registration completed successfully!")




        Catch ex As COMException


            My.Application.Log.WriteException(ex)
            MsgBox(ex.Message & "COM Exception")


        End Try


    End Sub

    Public Sub UnregisterIndexer()

        Try
            Dim gdsReg As New GoogleDesktopIndexingComponentRegister

            gdsReg.UnregisterIndexingComponent(MyGuid)


            'MessageBox.Show("Component unregistered successfully!")

            My.Application.Log.WriteEntry("Component Unregistered Successfully!", TraceEventType.Information)


        Catch ex As COMException

            My.Application.Log.WriteException(ex)
            MsgBox(ex.Message & "COM Exception")

        End Try

    End Sub


    Public Sub SendEvent(ByVal filename As String) ' , ByVal author As String, ByVal content As String)

        If String.IsNullOrEmpty(filename) Then
            My.Application.Log.WriteEntry("Try to Send NOT EXIST File! " & filename, TraceEventType.Information Or TraceEventType.Warning)

            Return
        End If

        Try



            Dim FileInfo As FileInfo = My.Computer.FileSystem.GetFileInfo(filename)

            Dim cachelen As Integer = CInt(FileInfo.Length * 2)

            Dim title As String
            Dim creator As String

            Dim xpsfile As New XpsDocument(filename, FileAccess.Read)
            My.Application.Log.WriteEntry("Created XPSDocument : " & filename, TraceEventType.Information)


            My.Application.Log.WriteEntry("Reading File : " & filename, TraceEventType.Information)



            Dim content = ReadXpsText(xpsfile, cachelen)

            title = If(xpsfile.CoreDocumentProperties.Title IsNot Nothing, xpsfile.CoreDocumentProperties.Title, FileInfo.Name)


            creator = If(xpsfile.CoreDocumentProperties.Creator IsNot Nothing, xpsfile.CoreDocumentProperties.Creator, String.Empty)

            xpsfile.Close()


            Dim gdsClass As New GoogleDesktop

            'Google.Desktop.File

            Dim gdsEventDisp = gdsClass.CreateEvent(MyGuid, "Google.Desktop.TextFile")

            My.Application.Log.WriteEntry("Send Event : Create Event :" & filename, TraceEventType.Information)


            Dim gdsEvent = CType(gdsEventDisp, IGoogleDesktopEvent2)



            'uri                  The file's URI. VT_BSTR Yes
            'last_modified_time   When the file was last modified in UTC. VT_DATE Yes
            'title                What title you choose to give the file, usually its filename. VT_BSTR No
            'author               The file's author.  VT_BSTR No

            'content              Contains the content to be indexed. The content must be in a text format (which can include HTML or similar markup, although GD will only treat HTML markup differently from plain text) not binary data. Note that some items may not have any indexable content, such as media files for which GD only indexes metadata and email messages with no content in their body. For those items, set this property to an empty string.  VT_BSTR Yes
            'format               Mime type of the indexable content, allowed values are text/plain and text/html.  VT_BSTR Yes
            'native_size          Size of the indexable content in bytes. Note that for file types for which there is no indexable content but still contain content, such as media files, you should set this property to be the size of the content. For example, for a 10 Megabyte audio file, you wouldn't put the 10 MB of content in an event's content property, but you should set its native_size property to 10000000.  VT_UI8 No
            'thumbnail            Thumbnail image of the content. We recommend the image be 109 pixels wide by 75 pixels tall. Image files of more than 20 KB will be rejected with an invalid argument error. If you specify a thumbnail image, you must also set a value for the following thumbnail_format property.  VT_ARRAY No
            'thumbnail_format     Mime type of the thumbnNail image, allowed values are image/gif, image/jpeg, and image/png.  VT_BSTR No
            'cookie               String cookie used to pass additional information identifying the event. VT_BSTR No
            'cookie_raw           Binary cookie. VT_ARRAY No
            'other_indexed_data   Contains optional indexable content and metadata. Can be used to index additional data that is separate from the content property VT_BSTR No
            'extra_data Contains  optional non-indexable string metadata for this event VT_BSTR No
            'extra_binary_data    Contains optional non-indexable binary metadata for this event VT_ARRAY No






            gdsEvent.AddProperty("format", "text/html")

            gdsEvent.AddProperty("content", content)

            My.Application.Log.WriteEntry("Send EVENT : content size: " & content.Length)

            gdsEvent.AddProperty("last_modified_time", FileInfo.LastWriteTime.ToOADate)

            gdsEvent.AddProperty("uri", filename)




            gdsEvent.AddProperty("title", title)


            gdsEvent.AddProperty("author", creator)

            gdsEvent.Send(EventFlags.EventFlagIndexable) ' Or EventFlags.EventFlagContextual Or EventFlags.EventFlagReplace)

            'Dim i = gdsEvent.SendEx(EventFlags.EventFlagIndexable )

            'My.Application.Log.WriteEntry("Send Event Result " & i & " File : " & filename)



            My.Application.Log.WriteEntry("Send Event : Sended event : " & filename, TraceEventType.Information)




        Catch ex As COMException

            My.Application.Log.WriteException(ex)
            MsgBox(ex.Message & "COM Exception")


        End Try


    End Sub


    Private Function ReadXpsText(ByRef xpsfile As XpsDocument, ByVal cachelen As Integer) As String

        If xpsfile.FixedDocumentSequenceReader Is Nothing Then Return String.Empty


        Dim sb As New StringBuilder(cachelen)

        Dim readerI = xpsfile.FixedDocumentSequenceReader

        Dim FixedDocuments = readerI.FixedDocuments




        For Each doc In FixedDocuments


            Dim pages As System.Collections.ObjectModel.ReadOnlyCollection(Of System.Windows.Xps.Packaging.IXpsFixedPageReader) = doc.FixedPages

            For Each page In pages


                Dim pagedoc = Xml.Linq.XDocument.Load(page.XmlReader)



                'Dim fixdpage = <FixedPage Width="1056" Height="816" xmlns="http://schemas.microsoft.com/xps/2005/06" xml:lang="und">
                '                   <Glyphs Fill="#ff000000" FontUri="/Documents/1/Resources/Fonts/3079F5B8-B92E-4BFD-AD17-B1EFF8B44A06.odttf" FontRenderingEmSize="12.0228" StyleSimulations="None" OriginX="51.04" OriginY="10.72" Indices="47;76,23;81;78,51;29;3;75;87,29;87;83;29;18;18,29;80,84;86;71;81;21,57;17;80,84;76,23;70;85;82;86,51;82;73,29;87,27;17;70,51;82;80,84;18;72,57;81;16;88;86,51;18;79,23;76;69;85,34;68;85,34;92,49;18;86,51;92,49;86;87;72,57;80;17;81;72,57;87;17;86,51;72;70,51;88;85;76,23;87;92,49;17;85,34;72;80,84;82;87;72;70,52;72,55;85,34;87;76,23;73,27;76,23;70,51;68;87;72;89;68;79,23;76,23;71;68;87;76,23;82;81,57;70;68;79,23;79,23;69;68;70,51;78,51;17;68;86,51;83;91" UnicodeString="Link: http://msdn2.microsoft.com/en-us/library/system.net.security.remotecertificatevalidationcallback.aspx"/>
                '               </FixedPage>

                'Dim Glyphss = From Glyphs In fixdpage...<eopr:Glyphs> _
                '              Select Glyphs

                Dim strs = From Glyphs In pagedoc...<eopr:Glyphs> _
                           Select Glyphs.@UnicodeString

                For Each s In strs

                    sb.AppendLine(s)

                Next

                sb.AppendLine()


            Next

            sb.AppendLine()

        Next

        Return sb.ToString
    End Function


    Public Function ReadXps(ByVal filename As String) As String

        Dim xpsfile As New XpsDocument(filename, FileAccess.Read)

        My.Application.Log.WriteEntry("Read File : " & filename, TraceEventType.Information)

        Return ReadXpsText(xpsfile, 10000)
    End Function


    'Public Class XpsInfo
    '    Dim Document As String

    '    Dim Category As String
    '    Dim ContentStatus As String
    '    Dim ContentType As String
    '    Dim Created As Date?
    '    Dim Creator As String
    '    Dim Description As String
    '    Dim Identifier As String
    '    Dim Keywords As String
    '    Dim Language As String
    '    Dim LastModifiedBy As String
    '    Dim LastPrinted As Date?
    '    Dim Modified As Date?
    '    Dim Revision As String
    '    Dim Subject As String
    '    Dim Title As String
    '    Dim Version As String


    'End Class


End Class


